home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / vol6n14.arc / DR.ASM next >
Assembly Source File  |  1987-05-14  |  65KB  |  1,412 lines

  1. ;            DR.asm
  2. ;  Format:   DR [d:][directory][/E][/S][/D][/T][/O]
  3.  
  4. CODE SEGMENT                           ;*************************;
  5. ASSUME CS:CODE,DS:CODE                 ;*                       *;
  6. ORG 100H                               ;*  REMEMBER TO EXE2BIN  *;
  7.                                        ;*                       *;
  8. START:         JMP    BEGINNING        ;*************************;
  9.  
  10. ;              DATA AREA
  11. ;              ---------
  12. ;              DB  'Copyright 1987 Ziff-Davis Publishing Co.'
  13. ;              DB  'Michael J. Mefford'
  14.  
  15. CURRENT_DISK   DB  ?
  16. STATUS_REG     DW  ?
  17. VIDEO_SEG      DW  0B000H
  18. NORMAL         DB  07H
  19. INVERSE        DB  70H
  20. BAR_ATTRIBUTE  DB  70H
  21. CURSOR_TYPE    DW  ?
  22.  
  23. SORT_OFFSET    DW  0
  24. SORT_TABLE     DW  0,12,9,3,13,8,29
  25. SORT_FLAG      DB  0
  26. CUR_OFFSET     DW  BUFFER
  27. CUR_FILE       DW  ?
  28. END_OFFSET     DW  ?
  29. PAGES          DW  ?
  30. PAGE_END       DW  21*160+323
  31. COUNT          DW  1
  32. LINE           DW  323
  33. STAR_DOT_STAR  DB  '*.*',0
  34. VERIFY_FLAG    DB  1
  35. WORDSTAR_BIT   DB  7FH
  36. SEARCH_COUNT   DW  ?
  37.  
  38. DISPATCH_KEY   DB  1,11H,12H,13H,14H,1CH,1FH,20H,2FH,31H,32H,3BH,3CH,3DH,3EH
  39.                DB    3FH,40H,41H,42H,43H,44H,47H,48H,49H,4FH,50H,51H,76H,84H
  40.  
  41. DISPATCH_TABLE DW  EXIT, WORDSTAR, SORT_EXT, RENAME, SORT_DATE, VIEW
  42.                DW  SORT_SIZE, DELETE, VIEW, SORT_NAME, MOVE, VIEW
  43.                DW  DELETE, RENAME, MOVE, VERIFY, WORDSTAR, SORT_NAME
  44.                DW  SORT_EXT, SORT_SIZE, SORT_DATE, HOME_BAR, UP_ARROW
  45.                DW  PG_UP, END_BAR, DN_ARROW, PG_DN, BOTTOM_BAR, TOP_BAR
  46.  
  47. VIEW_TABLE     DW  HOME_FILE, UP_LINE, UP_PG, END_FILE
  48.                DW  DN_LINE, DN_PG, END_FILE, HOME_FILE
  49.  
  50. DISPLAY_FLAG   DB  ?
  51. ROW            DB  0
  52. FILE_END       DW  ?
  53. FILE_HANDLE    DW  ?
  54. LAST_PAGE      DW  ?
  55.  
  56. NOT_ENOUGH     DB  'Not enough memory$'
  57. INVALID        DB  'Invalid directory$'
  58. TOO_MANY       DB  'Too many files$'
  59. LOADING        DB  'Loading and Sorting directory.',0
  60. LOAD_ONLY      DB  'Loading directory.',0
  61. DIRECTORY      DB  'Directory of ',0
  62. FILES          DB  '    Files',0
  63. DELETE_MSG     DB  ' will be deleted.',0,'Do you wish to delete it?  Y/N',0
  64. RENAME_MSG     DB  'Enter new name for ',0
  65. MOVE_MSG       DB  'Enter new directory for ',0
  66. ON             DB  ' ON',0
  67. OFF            DB  'OFF',0
  68. BS             DB  8,32,8,0
  69.  
  70. FILE_BUFFER    EQU    32767-256
  71. SIXTEEN_K      EQU    16384
  72.  
  73. MENU  LABEL  BYTE
  74. DB  201,20 DUP (205),187,186,' PC Magazine DR.COM ',186
  75. DB  186,' (C) Copr. 1987 ZD  ',186,186,' Michael J. Mefford ',186
  76. DB  199,20 DUP (196),182,186,' F1   View (or ',17,196,217,') ',186
  77. DB  186,' F2   Delete        ',186,186,' F3   Rename        ',186
  78. DB  186,' F4   Move          ',186,186,' F5   Confirm   ON  ',186
  79. DB  186,' F6   WordStar  ON  ',186,186,' F7   Sort by Name  ',186
  80. DB  186,' F8   Sort by Ext.  ',186,186,' F9   Sort by Size  ',186
  81. DB  186,' F10  Sort by daTe  ',186,186,' Esc  to Exit       ',186
  82. DB  200,20 DUP (205),188,'  Use: ',24,32,25,' PgUp PgDn  '
  83. DB  ' ^PgUp ^PgDn Home End '
  84.  
  85. ;----------------------------------------------------------------------------;
  86. ; Some housekeeping first. Since we will be changing the default drive       ;
  87. ; and directory to the requested drive and directory, we need to save the    ;
  88. ; current defaults, so they can be restored.  If less than 64K, exit.        ;
  89. ;----------------------------------------------------------------------------;
  90.  
  91. ;              CODE AREA
  92. ;              ---------
  93. BEGINNING:     MOV    AX,3301H               ;Turn Control Break off.
  94.                MOV    DL,0
  95.                INT    21H
  96.  
  97.                CLD                           ;String moves forward.
  98.                MOV    AH,19H                 ;Get current drive.
  99.                INT    21H
  100.                MOV    CURRENT_DISK,AL        ;And save.
  101.  
  102. ;---------------------------------------------------------------------;
  103. ; More housekeeping. We will be writing directly to the screen buffer ;
  104. ; so we need the display card address and the status register.        ;
  105. ;---------------------------------------------------------------------;
  106.  
  107. DISPLAY:       MOV    AX,40H           ;Point to the ROM BIOS data area
  108.                MOV    DS,AX            ; and get base address of active
  109.                MOV    AX,DS:[63H]      ; display card.
  110.                ADD    AX,6             ;Add six to get status register
  111.                PUSH   CS               ;Done there, so restore data segment.
  112.                POP    DS
  113.                MOV    STATUS_REG,AX    ;Store status register.
  114.                CMP    AX,3BAH          ;Status port of MONO card is 3BAh.
  115.                JZ     MONO             ;If that's what we got, it's MONO
  116.                MOV    VIDEO_SEG,0B800H       ; else COLOR so add 800h.
  117.                XOR    BH,BH                  ;Get current attribute
  118.                MOV    AH,8                   ; of display page zero.
  119.                INT    10H
  120.                MOV    NORMAL,AH              ;Store it.
  121.                XOR    AH,1110111B            ;Flip color bits.
  122.                MOV    INVERSE,AH             ;Save it.
  123.                MOV    BAR_ATTRIBUTE,AH
  124. MONO:          XOR    BH,BH
  125.                MOV    AH,3                   ;Retrieve cursor type.
  126.                INT    10H
  127.                MOV    CURSOR_TYPE,CX
  128.  
  129.                CMP    SP,65533               ;Do we have 64K?
  130.                MOV    DX,OFFSET NOT_ENOUGH
  131.                JA     PARSE
  132.                JMP    ERROR_EXIT             ;If no, exit.
  133.  
  134. ;----------------------------------------;
  135. ; Parse the command line for parameters. ;
  136. ;----------------------------------------;
  137.  
  138. PARSE:         CMP    BYTE PTR DS:[80H],0    ;Any parameters?
  139.                JNZ    GET_SWITCH             ;If yes, parse.
  140.                JMP    MESSAGE                ;Else, skip.
  141.  
  142. GET_SWITCH:    MOV    SI,81H                 ;Else, point to first character.
  143. NEXT_SWITCH:   LODSB                         ;Get a byte.
  144.                CMP    AL,13                  ;Carriage return?
  145.                JZ     GET_PARA               ;If yes, done here.
  146.                CMP    AL,'/'                 ;Is it switch character?
  147.                JNZ    NEXT_SWITCH            ;If no, get next character.
  148.                LODSB                         ;Get switch character.
  149.                AND    AL,5FH                 ;Capitalize.
  150.                CMP    AL,'E'                 ;If "E", sort by extension.
  151.                JNZ    CK_SIZE
  152.                MOV    SORT_OFFSET,4
  153. CK_SIZE:       CMP    AL,'S'                 ;If "S", sort by size.
  154.                JNZ    CK_DATE
  155.                MOV    SORT_OFFSET,8
  156. CK_DATE:       CMP    AL,'D'                 ;If "D", sort by date.
  157.                JZ     GOT_DATE
  158.                CMP    AL,'T'                 ;If "T", sort by date.
  159.                JNZ    CK_ORIGINAL
  160. GOT_DATE:      MOV    SORT_OFFSET,12
  161.  
  162. CK_ORIGINAL:   CMP    AL,'O'                 ;If "O", don't sort at all.
  163.                JNZ    GET_PARA
  164.                MOV    SORT_FLAG,1
  165.  
  166. GET_PARA:      MOV    SI,81H                 ;Point to first character.
  167. NEXT_PARSE:    LODSB
  168.                CMP    AL,13                  ;Carriage return or slash?
  169.                JZ     MESSAGE                ;If yes, done here.
  170.                CMP    AL,'/'
  171.                JZ     MESSAGE
  172.                CMP    AL,32                  ;Leading space?
  173.                JBE    NEXT_PARSE             ;If yes, get next byte.
  174.  
  175.                PUSH   SI                     ;Save start.
  176. NEXT_PARA:     LODSB
  177.                CMP    AL,32                  ;End of parameter?
  178.                JBE    END_PARA               ;If yes, done here.
  179.                CMP    AL,'/'
  180.                JZ     END_PARA
  181.                CMP    AL,':'                 ;Drive request?
  182.                JNZ    NEXT_PARA              ;If no, get next byte.
  183.                MOV    DL,BYTE PTR [SI-2]     ;Else, retrieve request.
  184.                AND    DL,5FH                 ;Capitalize.
  185.                SUB    DL,'A'                 ;Convert to DOS format.
  186.                MOV    AH,0EH                 ;And change drive.
  187.                INT    21H
  188.                JMP    SHORT NEXT_PARA        ;Find end of parameter.
  189.  
  190. END_PARA:      MOV    BYTE PTR DS:[SI-1],0   ;Convert parameter to ASCIIZ.
  191.                MOV    BL,BYTE PTR DS:[SI-2]
  192.                MOV    SI,OFFSET CURRENT_DIR  ;Get current directory.
  193.                CALL   GET_DIR
  194.                POP    DX                     ;Retrieve start.
  195.                DEC    DX                     ;Adjust.
  196.                CMP    BL,':'                 ;Is it a drive request?
  197.                JZ     MESSAGE                ;If yes, skip directory change.
  198.                CMP    BL,32                  ;Is it a delimiter?
  199.                JBE    MESSAGE                ;If yes, skip.
  200.                MOV    AH,3BH                 ;Change directory.
  201.                INT    21H
  202.                MOV    DX,OFFSET INVALID
  203.                JC     ERROR_EXIT             ;If error, exit.
  204.  
  205. MESSAGE:       CALL   CLS                    ;Clear screen.
  206.                CALL   CURSOR_OFF             ;Cursor off.
  207.                MOV    SI,OFFSET LOADING      ;Display sorting message.
  208.                MOV    DX,0C19H
  209.                CMP    SORT_FLAG,1            ;Unless not sorted.
  210.                JNZ    DISP_MSG
  211.                MOV    SI,OFFSET LOAD_ONLY    ;Then display loading message.
  212.                MOV    DX,0C1FH
  213. DISP_MSG:      CALL   DISPLAY_TEXT
  214.  
  215.                MOV    DI,OFFSET BUFFER       ;Put space character
  216.                MOV    CX,16000               ; in directory listing
  217.                MOV    AX,2020H               ; buffer.
  218.                REP    STOSW
  219.  
  220. ;------------------------------------------------------------------;
  221. ; Read all the directory filenames and store as records in buffer. ;
  222. ;------------------------------------------------------------------;
  223.  
  224. READ_DIR:      MOV    DX,OFFSET STAR_DOT_STAR
  225.                MOV    CX,7
  226.                MOV    AH,4EH                 ;Find first matching file.
  227.                INT    21H
  228.                JC     EXIT                   ;If empty directory, exit.
  229.  
  230. STORE_NAME:    MOV    DI,OFFSET BUFFER       ;Point to buffer.
  231.                MOV    BP,FILE_BUFFER-200     ;Reserve 32K for file read buffer
  232.                CALL   BUFFER_NAME            ;Convert to directory format.
  233.  
  234. FIND_NEXT:     MOV    AH,4FH                 ;Find next matching.
  235.                INT    21H
  236.                JC     STORE_COUNT            ;If carry, no more names.
  237.                INC    COUNT                  ;Increment count of names.
  238.                CALL   BUFFER_NAME
  239.                CMP    DI,BP                  ;Are we encroaching file buffer?
  240.                JBE    FIND_NEXT              ;If no, find next.
  241.                MOV    DX,OFFSET TOO_MANY     ;Else, exit with message.
  242.  
  243. ;-----------------------------------------------------------------------;
  244. ; This is the exit routine. Restore the defaults the way we found them. ;
  245. ;-----------------------------------------------------------------------;
  246.  
  247. ERROR_EXIT:    MOV    AH,9                    ;Display error message.
  248.                INT    21H
  249.                JMP    SHORT RESET
  250.  
  251. EXIT:          CALL   CLS                     ;Clear screen.
  252.                XOR    DX,DX                   ;Set cursor top left.
  253.                CALL   SET_CURSOR
  254.                CALL   CURSOR_ON               ;Turn cursor back on.
  255. RESET:         MOV    DX,OFFSET CURRENT_DIR   ;Reset the directory.
  256.                MOV    AH,3BH
  257.                INT    21H
  258.                MOV    DL,CURRENT_DISK         ;Reset the drive.
  259.                MOV    AH,0EH
  260.                INT    21H
  261.                INT    20H
  262.  
  263. ;-----------------------------------;
  264. ; Store buffer end address and page ;
  265. ; end then sort the filenames.      ;
  266. ;-----------------------------------;
  267.  
  268. STORE_COUNT:   MOV    END_OFFSET,DI          ;Store ending offset.
  269.                ADD    DI,40
  270.                MOV    PAGES,DI               ;Also, address for page storage.
  271.  
  272.                MOV    BX,COUNT               ;Retrieve file count.
  273.                CMP    BX,21                  ;Enough to fill one page?
  274.                JAE    DO_SORT                ;If yes, use default setting.
  275.                ADD    PAGES,800              ;Else, adjust page storage.
  276.                MOV    AX,160                 ;Calculate last record.
  277.                MUL    BL
  278.                ADD    AX,323                 ;Add bar offset.
  279.                MOV    PAGE_END,AX
  280. DO_SORT:       CMP    SORT_FLAG,1            ;Should we sort or leave original?
  281.                JZ     READY                  ;If it was "/O", don't sort.
  282.                CALL   SORT
  283.  
  284. ;------------------------------------------------------------------------;
  285. ; Now, we are ready to get target directory and display it and the menu. ;
  286. ;------------------------------------------------------------------------;
  287.  
  288. READY:         MOV    DI,OFFSET PURGE_DIR    ;Point to storage.
  289.                MOV    AH,19H
  290.                INT    21H                    ;Get drive.
  291.                ADD    AL,'A'                 ;Convert to ASCII.
  292.                STOSB
  293.                MOV    AL,':'                 ;Add colon.
  294.                STOSB
  295.                MOV    SI,DI                  ;Get directory.
  296.                CALL   GET_DIR
  297.                CALL   REFRESH_DIR            ;Display drive, directory, menu.
  298.  
  299. ;-----------------------------------------;
  300. ; We are ready for business now. We will  ;
  301. ; loop here, waiting for user keystrokes. ;
  302. ;-----------------------------------------;
  303.  
  304. GET_KEY:       CALL   UPDATE_SCREEN
  305.                CALL   READ_KEY               ;Get a keystroke.
  306.                MOV    BX,AX                  ;Save returned key.
  307.                CMP    AH,1                   ;Is it Esc or below?
  308.                JBE    FUNCTION               ;If yes, function.
  309.                CMP    AH,36H                 ;Is it right shift or above?
  310.                JAE    FUNCTION               ;If yes, function.
  311.                CMP    AH,1CH                 ;Is it CR?
  312.                JZ     FUNCTION               ;If yes, function.
  313.                MOV    AH,2                   ;Get shift state.
  314.                INT    16H
  315.                TEST   AL,4                   ;Is Ctrl depressed?
  316.                JNZ    FUNCTION               ;If no, check function request.
  317.                CALL   SEARCH                 ;Else, search for first letter.
  318.                JMP    SHORT GET_KEY
  319. FUNCTION:      MOV    DI,OFFSET DISPATCH_KEY
  320.                MOV    AL,BH
  321.                MOV    CX,29                  ;29 valid commands.
  322.                REPNZ  SCASB
  323.                JNZ    GET_KEY                       ;If no match, get another.
  324.                MOV    DI,OFFSET DISPATCH_TABLE+56
  325.                SHL    CX,1
  326.                SUB    DI,CX
  327.                CALL   DS:[DI]                ;Else do subroutine.
  328.                JMP    SHORT GET_KEY          ;Update screen; get next command.
  329.  
  330.                ;*************;
  331.                ; SUBROUTINES ;
  332.                ;*************;
  333.  
  334. ;--------------------------------------------------------------------------;
  335. ; These six subroutines control the bar and page of the directory listing. ;
  336. ;--------------------------------------------------------------------------;
  337.  
  338. UP_ARROW:      MOV    BP,-160                ;Move bar up one line.
  339.                JMP    SHORT BAR_MOVE
  340.  
  341. DN_ARROW:      MOV    BP,160                 ;Move bar down one line.
  342. BAR_MOVE:      CALL   SCROLL_BAR
  343.                RET
  344.  
  345. PG_UP:         MOV    BP,-40*21              ;Move up 21 lines.
  346.                CALL   SCROLL
  347.                JMP    SHORT BOTTOM_BAR
  348.  
  349. PG_DN:         MOV    BP,40*21               ;Move down 21 lines.
  350. MOVE_PAGE:     CALL   SCROLL
  351.                JMP    SHORT TOP_BAR          ;Move bar to top.
  352.  
  353. HOME_BAR:      MOV    CUR_OFFSET,OFFSET BUFFER   ;Move listing to beginning.
  354. TOP_BAR:       MOV    SI,323                     ;And move bar to top.
  355.                CALL   MOVE_BAR
  356.                RET
  357.  
  358. END_BAR:       MOV    BX,END_OFFSET          ;Move listing to last page.
  359.                SUB    BX,21*40
  360.                CMP    BX,OFFSET BUFFER
  361.                JBE    BOTTOM_BAR
  362.                MOV    CUR_OFFSET,BX
  363. BOTTOM_BAR:    MOV    SI,PAGE_END            ;And move bar to bottom.
  364.                SUB    SI,160
  365.                CALL   MOVE_BAR
  366.                RET
  367.  
  368. ;-----------------------------------------------------------------------;
  369. ; This subroutine searches for a filename with a specific first letter. ;
  370. ;-----------------------------------------------------------------------;
  371.  
  372. SEARCH:        CMP    BL,'a'                 ;Capitalize if lower case.
  373.                JB     SEARCH_IT
  374.                CMP    BL,'z'
  375.                JA     SEARCH_IT
  376.                AND    BL,5FH
  377. SEARCH_IT:     CALL   GET_NAME               ;Get current position.
  378.                XOR    DX,DX                  ;Zero out file counter.
  379.                MOV    DI,SI                  ;Store current position in DI.
  380.                MOV    SI,OFFSET BUFFER       ;Point to top of listing.
  381.                CMP    BYTE PTR [DI],BL       ;Are we currently at a match?
  382.                JNZ    NEXT_SEARCH            ;If no, start from top.
  383. FIND_START:    INC    DX                     ;Increment count.
  384.                ADD    SI,40                  ;Increment record.
  385.                CMP    SI,DI                  ;New record?
  386.                JBE    FIND_START             ;If no, find it.
  387.  
  388. NEXT_SEARCH:   CMP    BYTE PTR [SI],BL       ;Got a match?
  389.                JZ     FOUND_IT               ;If yes, process.
  390. INC_SEARCH:    ADD    SI,40                  ;Else, point to next record.
  391.                INC    DX
  392.                CMP    BYTE PTR [SI],32       ;End of listing?
  393.                JNZ    NEXT_SEARCH            ;If no, keep searching.
  394.                CALL   BEEP                   ;No matches, so beep.
  395.                RET
  396.  
  397. FOUND_IT:      MOV    CX,COUNT               ;Retrieve file count.
  398.                SUB    CX,DX                  ;Subtract search count.
  399.                MOV    SEARCH_COUNT,CX        ;And store.
  400.                MOV    CL,NORMAL              ;Turn off bar for now.
  401.                MOV    BAR_ATTRIBUTE,CL
  402.                CALL   END_BAR                ;First move to end.
  403.                JMP    SHORT FIND_IT
  404. NEXT_FIND:     CALL   UP_ARROW               ;Move up to matching filename.
  405. FIND_IT:       DEC    SEARCH_COUNT
  406.                JNZ    NEXT_FIND
  407.                MOV    CL,INVERSE             ;Turn bar back on and display.
  408.                MOV    BAR_ATTRIBUTE,CL
  409.                XOR    BP,BP
  410.                CALL   SCROLL_BAR
  411.                RET
  412.  
  413. ;------------------------------------------------------------;
  414. ; This subroutine displays the highlighted file for viewing. ;
  415. ;------------------------------------------------------------;
  416.  
  417. VIEW:          CALL   GET_NAME               ;Get the file name.
  418.                MOV    DX,OFFSET FILE_NAME    ;Open the file.
  419.                MOV    AX,3D00H
  420.                INT    21H
  421.                MOV    FILE_HANDLE,AX         ;Save filehandle.
  422.  
  423.                CALL   FIRST_READ
  424.                MOV    LAST_PAGE,OFFSET FILE_BUFFER+SIXTEEN_K
  425.                MOV    BP,PAGES               ;Initialize page pointer.
  426.                MOV    ROW,0                  ;And row pointer.
  427.                CALL   CLS                    ;Clear screen.
  428.  
  429. GET_VIEW:      MOV    SI,LAST_PAGE           ;Get top of current page.
  430.                MOV    BH,ROW                 ;Get row offset into page.
  431.                CMP    BH,0                   ;Is it row zero?
  432.                JZ     NEXT_VIEW              ;If yes, skip.
  433.                MOV    DISPLAY_FLAG,0         ;No display.
  434. PAGE_OFFSET:   CALL   LINES
  435.                DEC    BH
  436.                JNZ    PAGE_OFFSET
  437.  
  438. NEXT_VIEW:     MOV    BH,25                  ;Now display 25 lines.
  439.                XOR    DI,DI                  ;Start at top left corner.
  440.                MOV    DISPLAY_FLAG,1         ;Display.
  441. VIEW_DISPLAY:  CALL   LINES
  442.                DEC    BH
  443.                JNZ    VIEW_DISPLAY
  444.  
  445. VIEW_COMMAND:  CALL   READ_KEY               ;Get a keystroke.
  446.                CMP    AH,1                   ;Is it Esc?
  447.                JZ     VIEW_END               ;If yes, exit view.
  448.                CMP    AH,1CH                 ;Is it carriage return?
  449.                JZ     VIEW_END               ;If yes, exit view.
  450.                CMP    AH,3BH                 ;Is it F1?
  451.                JZ     VIEW_END               ;If yes, exit.
  452.                CMP    AH,20H                 ;Is it "D"?
  453.                JZ     VIEW_DELETE            ;If yes, go to delete function.
  454.                CMP    AH,3CH                 ;Is it F2?
  455.                JNZ    CK_RENAME              ;If no, check if rename request.
  456. VIEW_DELETE:   CALL   VIEW_REQUEST           ;Else, close file.
  457.                JMP    DELETE                 ;Go to delete function.
  458. CK_RENAME:     CMP    AH,13H                 ;Is it "R"?
  459.                JZ     VIEW_RENAME            ;If yes, go to rename function.
  460.                CMP    AH,3DH                 ;Is it F3?
  461.                JNZ    CK_MOVE                ;If no, check if move request.
  462. VIEW_RENAME:   CALL   VIEW_REQUEST
  463.                JMP    RENAME
  464. CK_MOVE:       CMP    AH,32H                 ;Is it "M"?
  465.                JZ     VIEW_MOVE              ;If yes, go to move function.
  466.                CMP    AH,3EH                 ;Is it F4?
  467.                JNZ    GET_DISPATCH           ;If no, get dispatch table.
  468. VIEW_MOVE:     CALL   VIEW_REQUEST
  469.                JMP    MOVE
  470. GET_DISPATCH:  MOV    DI,OFFSET DISPATCH_KEY+21
  471.                MOV    AL,AH
  472.                MOV    CX,8                   ;8 valid commands.
  473.                REPNZ  SCASB
  474.                JNZ    VIEW_COMMAND           ;If no, match, get next stroke.
  475.                MOV    DI,OFFSET VIEW_TABLE+14
  476.                SHL    CX,1
  477.                SUB    DI,CX
  478.                CALL   DS:[DI]                ;Do subroutine.
  479.                JC     VIEW_COMMAND           ;Carry indicates no screen update.
  480.                JMP    GET_VIEW               ;Else, update and get next command.
  481.  
  482. VIEW_END:      MOV    BX,FILE_HANDLE         ;Close the file.
  483.                MOV    AH,3EH
  484.                INT    21H
  485.                CALL   REFRESH_DIR            ;Restore menu.
  486.                RET
  487.  
  488. VIEW_REQUEST:  CALL   VIEW_END               ;If request of another function,
  489.                CALL   UPDATE_SCREEN          ; close file and update screen.
  490.                RET
  491.  
  492. ;----------------------------------------------------------------------;
  493. ; These six subroutines control the page and starting row of the view. ;
  494. ;----------------------------------------------------------------------;
  495.  
  496. UP_LINE:       CMP    ROW,0                  ;Are we at row zero?
  497.                JNZ    DEC_ROW                ;If no, decrement one row.
  498.                CMP    BP,PAGES               ;Else, are we at first page?
  499.                STC
  500.                JZ     UP_LINE_END            ;If yes, no change.
  501.                CALL   UP_PG                  ;Else, move up one page.
  502.                MOV    ROW,25                 ;And move starting row to 25.
  503. DEC_ROW:       DEC    ROW                    ;Decrement row.
  504.                CLC                           ;Flag to update screen.
  505. UP_LINE_END:   RET
  506.  
  507. DN_LINE:       CALL   CK_FILE_END            ;Are we at end of file?
  508.                JNC    CK_ROW                 ;If no, check row.
  509.                RET                           ;Else, return.
  510. CK_ROW:        CMP    ROW,24                 ;Are we at last row?
  511.                JB     INC_ROW                ;If no, increment row.
  512.                CALL   DN_PG                  ;Else, page down.
  513.                MOV    ROW,-1                 ;And move row to top.
  514. INC_ROW:       INC    ROW
  515.                CLC
  516. DN_LINE_END:   RET
  517.  
  518. UP_PG:         CMP    BP,PAGES               ;Are we already at first page?
  519.                JNZ    DEC_PG                 ;If no, decrement page.
  520.                CMP    ROW,0                  ;Are we at first row?
  521.                STC
  522.                JZ     UP_PG_END              ;If yes, no update.
  523.                MOV    ROW,0                  ;Else move to first row.
  524.                JMP    SHORT UPDATE_PAGE
  525. DEC_PG:        MOV    SI,LAST_PAGE           ;Get current page.
  526.                SUB    SI,DS:[BP]             ;Subtract difference to prev page.
  527.                CMP    SI,OFFSET FILE_BUFFER  ;Beyond top of buffer?
  528.                JAE    UP_PG_RET              ;If no, page up.
  529.                CALL   BACKWARD               ;Else, read in previous 16K
  530.                JMP    SHORT DEC_PG           ;Try again.
  531. UP_PG_RET:     DEC    BP
  532.                DEC    BP                     ;Decrement page pointer.
  533.                MOV    LAST_PAGE,SI           ;Store new starting position.
  534. UPDATE_PAGE:   CLC
  535. UP_PG_END:     RET
  536.  
  537. DN_PG:         CMP    BP,65535-256           ;Out of room for page storage?
  538.                JAE    NOUPDATE_PG            ;If yes, skip.
  539.                MOV    SI,LAST_PAGE           ;Else, retrieve current page.
  540.                MOV    DISPLAY_FLAG,0         ;No display.
  541.                MOV    BH,25                  ;Move up 25 lines.
  542. NEXT_PAGE:     CALL   LINES
  543.                DEC    BH
  544.                JNZ    NEXT_PAGE
  545.                CALL   CK_FILE_END            ;End of file?
  546.                JC     NOUPDATE_PG            ;If yes, no update.
  547. INC_PG:        MOV    DX,LAST_PAGE           ;Else, save current offset.
  548.                MOV    LAST_PAGE,SI           ;Store new offset.
  549.                MOV    AX,SI
  550.                SUB    AX,DX                  ;Get difference between pages.
  551.                INC    BP                     ;Increment page storage.
  552.                INC    BP
  553.                MOV    DS:[BP],AX             ;And store.
  554.                CLC
  555. DN_PG_END:     RET
  556. NOUPDATE_PG:   STC
  557.                RET
  558.  
  559. HOME_FILE:     CALL   UP_PG                  ;Page up until top of file.
  560.                JNC    HOME_FILE
  561.                CLC
  562.                RET
  563.  
  564. END_FILE:      CALL   DN_PG                  ;Page down until end of file.
  565.                JNC    END_FILE
  566.                CLC
  567.                RET
  568.  
  569. ;----------------------------------------------------------------;
  570. ; This subroutine checks to see if end of file has been reached. ;
  571. ;----------------------------------------------------------------;
  572.  
  573. CK_FILE_END:   CMP    SI,FILE_END
  574.                JB     NOT_FILE_END
  575.                CMP    FILE_END,OFFSET FILE_BUFFER+(SIXTEEN_K * 2)
  576.                JAE    NOT_FILE_END
  577.                STC
  578.                RET
  579. NOT_FILE_END:  CLC
  580.                RET
  581.  
  582. ;----------------------------------------------------------------;
  583. ; This subroutine formats the text into lines.  A line is marked ;
  584. ; by either a carriage return or reaching the last column (80).  ;
  585. ;----------------------------------------------------------------;
  586.  
  587. LINES:         MOV    CX,80                  ;80 columns.
  588. NEXT_LINES:    CMP    SI,FILE_END            ;If end of file, pad with spaces.
  589.                JB     GET_LINES
  590.                CMP    FILE_END,OFFSET FILE_BUFFER+ (SIXTEEN_K * 2)
  591.                JB     PAD_SPACES
  592.                PUSH   BX                     ;If end of buffer, save
  593.                PUSH   CX                     ; our pointers and
  594.                PUSH   DI                     ; read next 16K.
  595.                CALL   FORWARD
  596.                POP    DI                     ;Restore pointers.
  597.                POP    CX
  598.                POP    BX
  599.  
  600. GET_LINES:     LODSB                         ;Get a byte.
  601.                AND    AL,WORDSTAR_BIT        ;Strip high bit for WordStar?
  602.                CMP    AL,13                  ;Carriage return?
  603.                JZ     PAD_SPACES             ;If yes, pad balance of line.
  604.                CMP    AL,9                   ;Is it tab character?
  605.                JZ     TAB                    ;If yes, tab.
  606.                CMP    AL,10                  ;Is it linefeed?
  607.                JZ     NEXT_LINES             ;If yes, skip.
  608.                PUSH   CX                     ;Save counter.
  609.                MOV    CX,1                   ;Else, display one character.
  610.                CALL   CK_DISPLAY
  611.                POP    CX
  612. NEXT_BYTES:    LOOP   NEXT_LINES             ;Get next byte.
  613.                CMP    BYTE PTR [SI],13       ;Is this a eighty column line?
  614.                JNZ    END_LINES              ;If no, skip.
  615.                INC    SI                     ;Else, bump pointer past CR.
  616. END_LINES:     RET
  617.  
  618. TAB:           PUSH   CX                     ;Save counter.
  619.                DEC    CX                     ;Adjust column counter.
  620.                AND    CX,7                   ;Get bottom three bits.
  621.                INC    CX                     ;Adjust.
  622.                PUSH   CX
  623.                CALL   PAD_SPACES             ;Move to next tab position.
  624.                POP    AX
  625.                POP    CX
  626.                SUB    CX,AX                  ;Adjust counter.
  627.                JNZ    NEXT_LINES             ;Next byte if not column 80.
  628.                RET
  629.  
  630. PAD_SPACES:    MOV    AL,32                  ;Space character.
  631. CK_DISPLAY:    CMP    DISPLAY_FLAG,1         ;Are we to write it to screen?
  632.                JNZ    CK_DISP_END            ;If no, return.
  633.                MOV    BL,AL
  634. WRITE_VIEW:    CALL   WRITE_SCREEN           ;Else, write CX spaces.
  635.                LOOP   WRITE_VIEW
  636. CK_DISP_END:   RET
  637.  
  638. ;-------------------------------------------------------------------;
  639. ; These two subroutines read either the next or previous 16K bytes. ;
  640. ;-------------------------------------------------------------------;
  641.  
  642. FORWARD:       SUB    LAST_PAGE,SIXTEEN_K    ;Adjust current page offset.
  643.                XOR    CX,CX                  ;Move file pointer
  644.                MOV    DX,SIXTEEN_K           ; forward 16K.
  645.                CALL   MOVE_POINTER
  646. FIRST_READ:    MOV    SI,OFFSET FILE_BUFFER+SIXTEEN_K
  647.                MOV    DI,OFFSET FILE_BUFFER  ;Move second half of buffer
  648.                CALL   MOVE_BUFFER            ; to first half and read 16K.
  649.                MOV    CX,-1                  ;Move file pointer back.
  650.                NEG    DX
  651.                CALL   MOVE_POINTER
  652.                RET
  653.  
  654. BACKWARD:      ADD    LAST_PAGE,SIXTEEN_K    ;Adjust current page offset.
  655.                MOV    CX,-1                  ;Move pointer back 32K.
  656.                MOV    DX,- (SIXTEEN_K * 2)
  657.                CALL   MOVE_POINTER
  658.                MOV    SI,OFFSET FILE_BUFFER            ;Move first half of
  659.                MOV    DI,OFFSET FILE_BUFFER+SIXTEEN_K  ; buffer to second
  660.                CALL   MOVE_BUFFER                      ; and read 16K.
  661.                RET
  662.  
  663. MOVE_POINTER:  MOV    BX,FILE_HANDLE
  664.                MOV    AX,4201H               ;Move file pointer.
  665.                INT    21H
  666.                RET
  667.  
  668. MOVE_BUFFER:   MOV    DX,SI                  ;Save pointer.
  669.                MOV    CX,SIXTEEN_K / 2       ;Move 8K words (16K bytes).
  670.                REP    MOVSW
  671.                MOV    BX,FILE_HANDLE
  672.                MOV    CX,SIXTEEN_K           ;Read 16K.
  673.                MOV    AH,3FH
  674.                INT    21H
  675.                MOV    SI,DX
  676.                MOV    DX,AX
  677.                ADD    AX,OFFSET FILE_BUFFER+SIXTEEN_K
  678.                MOV    FILE_END,AX            ;Store end of buffer offset.
  679.                RET
  680.  
  681. ;-----------------------------------------------;
  682. ; This subroutine deletes the highlighted file. ;
  683. ;-----------------------------------------------;
  684.  
  685. DELETE:        CALL   GET_NAME                  ;Format the name for DOS.
  686.                JC     DELETE_ERROR              ;If yes, skip.
  687.                CMP    VERIFY_FLAG,0             ;Are we to warn before deleting?
  688.                JZ     DELETE_FILE            ;If no, skip.
  689.                MOV    SI,OFFSET FILE_NAME    ;Else, display warning message.
  690.                MOV    DX,162DH
  691.                CALL   DISPLAY_TEXT
  692.                MOV    SI,OFFSET DELETE_MSG
  693.                CALL   GET_TEXT
  694.                MOV    DX,172DH
  695.                CALL   DISPLAY_TEXT
  696.  
  697. QUERY:         CALL   READ_KEY               ;Get a keystroke.
  698.                CMP    AH,31H                 ;Is it "N"?
  699.                JZ     DELETE_END             ;If yes, exit delete.
  700.                CMP    AH,1                   ;Is it Esc?
  701.                JZ     DELETE_END             ;If yes, exit delete.
  702.                CMP    AH,15H                 ;Is it "Y"?
  703.                JZ     DELETE_FILE            ;If yes, delete
  704.                CALL   BEEP                   ;Else, beep.
  705.                JMP    SHORT QUERY            ;And get another keystroke.
  706.  
  707. DELETE_FILE:   MOV    DX,OFFSET FILE_NAME    ;Delete the file.
  708.                MOV    AH,41H
  709.                INT    21H
  710.                JC     DELETE_ERROR
  711.                CALL   REMOVE_FILE            ;Remove the file from the listing.
  712. DELETE_END:    CALL   CLEAR_MSG              ;Remove warning message.
  713.                RET
  714. DELETE_ERROR:  CALL   BEEP                   ;Beep if error.
  715.                CALL   CLEAR_MSG
  716.                RET
  717.  
  718. ;-----------------------------------------------;
  719. ; This subroutine renames the highlighted file. ;
  720. ;-----------------------------------------------;
  721.  
  722. RENAME:        CALL   GET_NAME                  ;Format name for DOS.
  723.                JC     RENAME_ERROR
  724.                MOV    DX,162CH                  ;Display rename message.
  725.                MOV    SI,OFFSET RENAME_MSG
  726.                CALL   DISPLAY_TEXT
  727.                MOV    SI,OFFSET FILE_NAME
  728.                CALL   GET_TEXT
  729.                MOV    DX,172CH
  730.                CALL   CLEAR_OLD              ;Remove last entry.
  731.  
  732. NEW_NAME:      CALL   READ_KEY               ;Get a character.
  733.                CMP    AL,27                  ;Is it Esc?
  734.                JZ     RENAME_END             ;Is yes, exit rename.
  735.                CMP    AL,':'                 ;Ignore ":\?* ".
  736.                JZ     NEW_NAME
  737.                CMP    AL,' '
  738.                JZ     NEW_NAME
  739.                CMP    AL,'\'
  740.                JZ     NEW_NAME
  741.                CMP    AL,'?'
  742.                JZ     NEW_NAME
  743.                CMP    AL,'*'
  744.                JZ     NEW_NAME
  745.                CMP    AL,13                  ;Is it carriage return?
  746.                JZ     RENAME_IT              ;If yes, rename it.
  747.                CMP    AL,8                   ;Is it backspace?
  748.                JNZ    NOT_BS1
  749.                CALL   MOVE_BS                ;If yes, backspace.
  750.                JMP    SHORT NEW_NAME
  751. NOT_BS1:       CMP    AL,32                  ;Is it space or above?
  752.                JB     NEW_NAME               ;If no, ignore.
  753.                CMP    DI,8CH                 ;End of entry field?
  754.                JZ     NEW_NAME               ;If yes, ignore.
  755.                STOSB                         ;Else, store byte.
  756.                CALL   WRITE_TEXT             ;And write it to screen.
  757.                JMP    SHORT NEW_NAME         ;Get next keystroke.
  758.  
  759. RENAME_IT:     CALL   RENAME_FILE            ;Rename the file.
  760.                JC     RENAME_ERROR           ;Beep if illegal.
  761.                MOV    DX,80H                 ;Else, place new name in listing.
  762.                MOV    CX,7
  763.                MOV    AH,4EH
  764.                INT    21H
  765.                MOV    DI,CUR_FILE
  766.                CALL   BUFFER_NAME
  767.  
  768. RENAME_END:    CALL   CURSOR_OFF             ;Turn cursor back off.
  769.                CALL   CLEAR_MSG              ;And clear rename message.
  770. RENAME_RET:    RET
  771. RENAME_ERROR:  CALL   BEEP                   ;Illegal entry exit.
  772.                CALL   CURSOR_OFF
  773.                CALL   CLEAR_MSG
  774.                RET
  775.  
  776. ;----------------------------------------------------------------;
  777. ; This subroutine moves the highlighted file to a new directory. ;
  778. ;----------------------------------------------------------------;
  779.  
  780. MOVE:          CALL   GET_NAME                  ;Format the name for DOS.
  781.                JC     MOVE_ERROR
  782.                MOV    DX,162BH                  ;Display the move message.
  783.                MOV    SI,OFFSET MOVE_MSG
  784.                CALL   DISPLAY_TEXT
  785.                MOV    SI,OFFSET FILE_NAME
  786.                CALL   GET_TEXT
  787.                MOV    DX,172BH
  788.                CALL   CLEAR_OLD              ;Remove previous entry.
  789.  
  790. NEW_DIR:       CALL   READ_KEY               ;Get a keystroke.
  791.                CMP    AL,27                  ;Is it Esc?
  792.                JZ     MOVE_END               ;If yes, exit move.
  793.                CMP    AL,':'                 ;Is it ":"?
  794.                JZ     NEW_DIR                ;If yes, skip
  795.                CMP    AL,13                  ;Is it carriage return?
  796.                JZ     MOVE_IT                ;If yes, move it.
  797.                CMP    AL,8                   ;If it backspace?
  798.                JNZ    NOT_BS2
  799.                CALL   MOVE_BS                ;If yes, backspace.
  800.                JMP    SHORT NEW_DIR
  801. NOT_BS2:       CMP    AL,32                  ;Is it space or above?
  802.                JB     NEW_DIR                ;If no, ignore.
  803.                CMP    DI,0A4H                ;Is it at end of entry field?
  804.                JZ     NEW_DIR                ;If yes, ignore.
  805.                STOSB                         ;Else, store the byte.
  806.                CALL   WRITE_TEXT             ;And write it to screen.
  807.                JMP    SHORT NEW_DIR          ;Get next keystroke.
  808.  
  809. MOVE_IT:       CMP    BYTE PTR DS:[80H],32   ;No entry?
  810.                JZ     MOVE_ERROR             ;If yes, error.
  811.                MOV    SI,OFFSET FILE_NAME    ;Point to filename.
  812.                MOV    AL,'\'
  813.                CMP    DS:[DI-1],AL           ;Did user add "\"?
  814.                JZ     ADD_FILENAME           ;If yes, skip.
  815.                STOSB                         ;Else, we have to add it.
  816. ADD_FILENAME:  MOVSB                         ;And filename to path.
  817.                CMP    BYTE PTR DS:[SI],0
  818.                JNZ    ADD_FILENAME
  819.                CALL   RENAME_FILE            ;Rename it.
  820.                JC     MOVE_ERROR             ;Beep if illegal.
  821.                CALL   REMOVE_FILE            ;Else remove from listing.
  822. MOVE_END:      CALL   CURSOR_OFF             ;Cursor back off.
  823.                CALL   CLEAR_MSG              ;Clear move message.
  824.                RET
  825. MOVE_ERROR:    CALL   BEEP                   ;Illegal move exit.
  826.                CALL   CURSOR_OFF
  827.                CALL   CLEAR_MSG
  828.                RET
  829.  
  830. ;-----------------------------------------------------------------------------;
  831. ; This subroutine toggles the delete confirm and WordStar message on and off. ;
  832. ;-----------------------------------------------------------------------------;
  833.  
  834. VERIFY:        XOR    VERIFY_FLAG,1               ;Toggle flag.
  835.                MOV    DI,OFFSET MENU+(9*22)+16    ;Point to menu.
  836.                MOV    SI,OFFSET ON                ;Assume "ON".
  837.                CMP    VERIFY_FLAG,1               ;Is it on?
  838.                JZ     TOGGLE                      ;If yes, store.
  839.                MOV    SI,OFFSET OFF               ;Else, store "OFF".
  840.                JMP    SHORT TOGGLE
  841.  
  842. WORDSTAR:      XOR    WORDSTAR_BIT,80H            ;Toggle flag.
  843.                MOV    DI,OFFSET MENU+(10*22)+16   ;Point to menu.
  844.                MOV    SI,OFFSET ON                ;Assume "ON".
  845.                CMP    WORDSTAR_BIT,7FH            ;Is it on?
  846.                JZ     TOGGLE                      ;If yes, store.
  847.                MOV    SI,OFFSET OFF               ;Else, store "OFF".
  848.  
  849. TOGGLE:        MOV    CX,3
  850.                REP    MOVSB
  851.                CALL   REFRESH_MENU                ;Display.
  852.                RET
  853.  
  854. ;------------------------------------------------------------------------;
  855. ; These four subroutines control in which column the sorting will start. ;
  856. ;------------------------------------------------------------------------;
  857.  
  858. SORT_NAME:     MOV    SORT_OFFSET,0
  859.                JMP    SHORT SORT_MSG
  860.  
  861. SORT_EXT:      MOV    SORT_OFFSET,4
  862.                JMP    SHORT SORT_MSG
  863.  
  864. SORT_SIZE:     MOV    SORT_OFFSET,8
  865.                JMP    SHORT SORT_MSG
  866.  
  867. SORT_DATE:     MOV    SORT_OFFSET,12
  868. SORT_MSG:      MOV    DX,1633H
  869.                MOV    SI,OFFSET LOADING+12
  870.                CALL   DISPLAY_TEXT
  871.  
  872. ;------------------------------------------;
  873. ; This subroutine does the actual sorting. ;
  874. ;------------------------------------------;
  875.  
  876. SORT:          CMP    COUNT,1
  877.                JZ     SORT_RETURN
  878.                MOV    DX,END_OFFSET          ;End of filenames in DX.
  879.                SUB    DX,40
  880.                MOV    BP,SORT_OFFSET
  881. NEXT_PASS:     MOV    SORT_FLAG,0
  882.                MOV    BX,OFFSET BUFFER       ;Point to start of buffer.
  883.  
  884. NEXT_SORT:     MOV    SI,BX                  ;Source and destination.
  885.                ADD    SI,SORT_TABLE[BP]
  886.                MOV    DI,SI
  887.                ADD    DI,40
  888.                CMP    BP,12                  ;Is it special case of date?
  889.                JZ     DO_DATE                ;If yes, go do it.
  890.                MOV    CX,SORT_TABLE[BP+2]
  891. COMPARE:       REPZ   CMPSB                  ;Compare filenames.
  892.                JBE    END_SORT               ;If already in order, skip.
  893.  
  894. SWAP:          MOV    SI,BX                  ;Else, recover pointers.
  895.                MOV    DI,BX
  896.                ADD    DI,40
  897.                MOV    CX,20                  ;Exchange the records.
  898. NEXT_SWAP:     MOV    AX,[DI]
  899.                MOVSW
  900.                MOV    [SI-2],AX
  901.                LOOP   NEXT_SWAP
  902.                MOV    SORT_FLAG,1            ;Flag that exchange was made.
  903.  
  904. END_SORT:      ADD    BX,40                  ;Point to next record.
  905.                CMP    BX,DX                  ;End of top?
  906.                JB     NEXT_SORT              ;If no, bubble sort next.
  907.                SUB    DX,40                  ;Else, move top down one record.
  908.                CMP    SORT_FLAG,0            ;Was there exchange made?
  909.                JNZ    NEXT_PASS              ;If yes, another pass.
  910. SORT_RETURN:   CALL   CLEAR_MSG
  911.                RET
  912.  
  913. DO_DATE:       MOV    CX,2                   ;Compare year first.
  914.                REPZ   CMPSB
  915.                JA     SWAP                   ;If above, swap.
  916.                JNZ    END_SORT
  917.                SUB    SI,8                   ;Else, adjust and do month/day.
  918.                SUB    DI,8
  919.                MOV    CX,5
  920.                REPZ   CMPSB
  921.                JA     SWAP                   ;If above, swap.
  922.                JNZ    END_SORT
  923.                ADD    SI,10                  ;Else, adjust and do meridian.
  924.                ADD    DI,10
  925.                CMPSB
  926.                JA     SWAP                   ;If above, swap.
  927.                JNZ    END_SORT
  928.                SUB    SI,6                   ;Else, adjust and do time.
  929.                SUB    DI,6
  930.                MOV    CX,5
  931.                CMP    WORD PTR [SI],3231H    ;Is it special case "12:"?
  932.                JZ     CK_MERIDIAN            ;If yes, see if same.
  933.                CMP    WORD PTR [DI],3231H    ;Is destination "12:"?
  934.                JNZ    COMPARE                ;If no, normal compare.
  935.                JMP    SWAP                   ;Else, swap.
  936. CK_MERIDIAN:   CMPSW                         ;Are both "12:"?
  937.                JNZ    END_SORT               ;If no, next record.
  938.                MOV    CX,3                   ;Else compare minutes.
  939.                JMP    SHORT COMPARE
  940.  
  941. ;--------------------------------------------------------------------------;
  942. ; This subroutine gets the highlighted file and converts it to DOS format. ;
  943. ;--------------------------------------------------------------------------;
  944.  
  945. GET_NAME:      MOV    SI,CUR_OFFSET          ;Get top of page.
  946.                MOV    AX,LINE                ;Get location of bar.
  947.                SUB    AX,323                 ;Adjust.
  948.                MOV    CL,2                   ;Convert to byte pointer.
  949.                SHR    AX,CL
  950.                ADD    SI,AX                  ;Add to current offset.
  951.                MOV    CUR_FILE,SI            ;And save pointer.
  952.                PUSH   SI
  953.                MOV    DI,OFFSET FILE_NAME    ;Store the first eight characters.
  954.                MOV    CX,8
  955.                CALL   STORE_BYTES
  956.                INC    SI
  957.                CMP    BYTE PTR DS:[SI],32    ;End of name?
  958.                JZ     END_NAME               ;If yes, done here.
  959.                MOV    AL,'.'                 ;Else, add dot.
  960.                STOSB
  961.                MOV    CX,3                   ;Three possible characters
  962.                CALL   STORE_BYTES            ; as extension.
  963. END_NAME:      MOV    BYTE PTR DS:[DI],0     ;Convert to ASCIIZ.
  964.                POP    SI
  965.                CMP    BYTE PTR [SI+39],'H'   ;Is it a hidden file?
  966.                STC
  967.                JZ     NAME_ERROR             ;If yes, indicate so.
  968.                CLC
  969. NAME_ERROR:    RET
  970.  
  971. STORE_BYTES:   LODSB                         ;Get a character.
  972.                CMP    AL,32                  ;If it's space, skip.
  973.                JZ     SKIP_STORE
  974.                STOSB
  975. SKIP_STORE:    LOOP   STORE_BYTES
  976.                RET
  977.  
  978. ;-----------------------------------------------------------;
  979. ; This subroutine moves and turns the cursor on and removes ;
  980. ; the last user entry in preparation for new input.         ;
  981. ;-----------------------------------------------------------;
  982.  
  983. CLEAR_OLD:     CALL   SET_CURSOR             ;Move cursor.
  984.                CALL   CURSOR_ON              ;Turn it on.
  985.                MOV    DI,80H                 ;Write spaces over old entry.
  986.                MOV    AX,2020H
  987.                MOV    CX,18
  988.                REP    STOSW
  989.                MOV    DI,80H                 ;Initiate pointer for entry.
  990.                RET
  991.  
  992. ;-----------------------------;
  993. ; This subroutine backspaces. ;
  994. ;-----------------------------;
  995.  
  996. MOVE_BS:       CMP    DI,80H                 ;At beginning of field?
  997.                JZ     MOVE_BS_END            ;If yes, skip.
  998.                DEC    DI                     ;Else, decrement pointer.
  999.                MOV    SI,OFFSET BS           ;Erase last character.
  1000.                CALL   GET_TEXT
  1001. MOVE_BS_END:   RET
  1002.  
  1003. ;--------------------------------------------;
  1004. ; This subroutine renames or moves the file. ;
  1005. ;--------------------------------------------;
  1006.  
  1007. RENAME_FILE:   MOV    BYTE PTR DS:[DI],0     ;Convert to ASCIIZ.
  1008.                MOV    DX,OFFSET FILE_NAME    ;Point to old name.
  1009.                MOV    DI,80H
  1010.                MOV    AH,56H                 ;Rename.
  1011.                INT    21H
  1012.                RET
  1013.  
  1014. ;------------------------------------------------------------------;
  1015. ; This subroutine removes the filename from the directory listing. ;
  1016. ;------------------------------------------------------------------;
  1017.  
  1018. REMOVE_FILE:   MOV    DI,CUR_FILE            ;Point to filename.
  1019.                MOV    SI,DI                  ;Move all the records
  1020.                ADD    SI,40                  ; that follow up one.
  1021. NEXT_RECORD:   MOV    CX,20
  1022.                REP    MOVSW
  1023.                CMP    DI,END_OFFSET
  1024.                JB     NEXT_RECORD
  1025.                SUB    DI,40
  1026.                MOV    END_OFFSET,DI          ;Store new end.
  1027.                XOR    BP,BP
  1028.                CALL   SCROLL                 ;Update the screen.
  1029.                DEC    COUNT                  ;Decrement file count.
  1030.                JNZ    MORE_FILES             ;If empty, exit.
  1031.                JMP    EXIT
  1032. MORE_FILES:    CMP    COUNT,21               ;Full page?
  1033.                JAE    REMOVE_END             ;If yes, skip.
  1034.                SUB    PAGE_END,160           ;Else, adjust page end.
  1035.                MOV    SI,PAGE_END
  1036.                SUB    SI,160
  1037.                CMP    SI,LINE                ;Is bar below directory listing?
  1038.                JA     REMOVE_END             ;If no, skip.
  1039.                CALL   MOVE_BAR               ;Else, move bar up one line.
  1040. REMOVE_END:    CALL   FILE_COUNT             ;Update file count on screen.
  1041.                RET
  1042.  
  1043. ;----------------------------------------------;
  1044. ; This subroutine displays the count of files. ;
  1045. ;----------------------------------------------;
  1046.  
  1047. FILE_COUNT:    MOV    DI,OFFSET FILES        ;Blank out previous count.
  1048.                MOV    AX,2020H
  1049.                STOSW
  1050.                MOV    AX,COUNT
  1051.                MOV    BL,10                  ;Convert to decimal.
  1052.                STD                           ;Reverse direction.
  1053. NEXT_COUNT:    DIV    BL
  1054.                XCHG   AL,AH
  1055.                ADD    AL,'0'                 ;Convert to ASCII.
  1056.                STOSB                         ;Store the remainder.
  1057.                XCHG   AL,AH
  1058.                XOR    AH,AH
  1059.                CMP    AX,0                   ;Are we done?
  1060.                JNZ    NEXT_COUNT
  1061.                CLD                           ;Back to forward direction.
  1062.                MOV    DX,180EH               ;Row 24; column 13.
  1063.                MOV    SI,OFFSET FILES        ;Display file count.
  1064.                CALL   DISPLAY_TEXT
  1065.                RET
  1066.  
  1067. ;----------------------------------------------------------------------------;
  1068. ; This subroutine displays the current directory, menu, and number of files. ;
  1069. ;----------------------------------------------------------------------------;
  1070.  
  1071. REFRESH_DIR:   CALL   CLS                    ;Clear the screen.
  1072. REFRESH_MENU:  MOV    SI,OFFSET MENU         ;Point to menu position.
  1073.                MOV    DI,(2*160)+98          ;And to screen position.
  1074.                MOV    BH,19                  ;Display 19 lines of menu.
  1075. NEXT_REFRESH:  MOV    CX,22                  ;22 characters per line.
  1076. NEXT_MENU:     LODSB
  1077.                MOV    BL,AL
  1078.                CALL   WRITE_SCREEN
  1079.                LOOP   NEXT_MENU
  1080.                ADD    DI,116                 ;Next line.
  1081.                DEC    BH
  1082.                JNZ    NEXT_REFRESH
  1083.  
  1084.                MOV    DX,4
  1085.                MOV    SI,OFFSET DIRECTORY    ;Display "Directory ".
  1086.                CALL   DISPLAY_TEXT
  1087.                MOV    SI,OFFSET PURGE_DIR    ;Display working directory.
  1088.                CALL   GET_TEXT
  1089.                CALL   FILE_COUNT             ;Display file count.
  1090.                MOV    BL,INVERSE             ;Put up cursor bar.
  1091.                CALL   BAR
  1092.                RET
  1093.  
  1094. ;-------------------------------------;
  1095. ; This subroutine scrolls the screen. ;
  1096. ;-------------------------------------;
  1097.  
  1098. SCROLL:        MOV    SI,CUR_OFFSET          ;Get current offset.
  1099.                ADD    SI,BP                  ;Add requested direction.
  1100. CK_LOWER:      CMP    SI,OFFSET BUFFER       ;If above start check upper limit.
  1101.                JAE    UPPER_LIMIT
  1102. LOWER_LIMIT:   MOV    CUR_OFFSET,OFFSET BUFFER    ;Else, make it start.
  1103.                JMP    SHORT SCROLL_RETURN         ;And update screen.
  1104.  
  1105. UPPER_LIMIT:   MOV    BX,END_OFFSET               ;See if beyond end of
  1106.                CMP    BX,OFFSET BUFFER+21*40      ; directory listing as well.
  1107.                JA     CK_UPPER
  1108.                MOV    CUR_OFFSET,OFFSET BUFFER
  1109.                JMP    SHORT SCROLL_RETURN
  1110.  
  1111. CK_UPPER:      SUB    BX,21*40
  1112.                CMP    SI,BX
  1113.                JBE    END_SCROLL
  1114.                MOV    SI,BX
  1115.  
  1116. END_SCROLL:    MOV    CUR_OFFSET,SI          ;Update current offset.
  1117. SCROLL_RETURN: RET
  1118.  
  1119. ;--------------------------------------------------;
  1120. ; This subroutine scrolls the bar if between start ;
  1121. ; and end of page. Otherwise the page is scrolled. ;
  1122. ;--------------------------------------------------;
  1123.  
  1124. SCROLL_BAR:    MOV    SI,LINE                ;Get current line.
  1125.                ADD    SI,BP                  ;Add requested line.
  1126.                MOV    BP,-40                 ;Assume below beginning.
  1127.                CMP    SI,323                 ;Is it?
  1128.                JB     SCROLL_PAGE            ;If yes, scroll page instead.
  1129.                MOV    BP,40                  ;Do the same for end of page.
  1130.                CMP    SI,PAGE_END
  1131.                JAE    SCROLL_PAGE
  1132.                CALL   MOVE_BAR
  1133.                RET
  1134.  
  1135. SCROLL_PAGE:   CALL   SCROLL
  1136.                RET
  1137.  
  1138. ;----------------------------------------------------;
  1139. ; This subroutine does the actual moving of the bar. ;
  1140. ;----------------------------------------------------;
  1141.  
  1142. MOVE_BAR:      MOV    BL,NORMAL              ;Remove old bar.
  1143.                CALL   BAR
  1144.                MOV    LINE,SI                ;And move bar to new line.
  1145.                MOV    BL,BAR_ATTRIBUTE
  1146.                CALL   BAR
  1147.                RET
  1148.  
  1149. BAR:           MOV    DI,LINE                ;Retrieve line.
  1150.                MOV    CX,39                  ;Bar length 39.
  1151. NEXT_BAR:      CALL   WRITE_SCREEN           ;Write the attribute.
  1152.                LOOP   NEXT_BAR
  1153.                RET
  1154.  
  1155. ;-------------------------------------------------;
  1156. ; This subroutine displays the directory listing. ;
  1157. ;-------------------------------------------------;
  1158.  
  1159. UPDATE_SCREEN: XOR    BP,BP
  1160.                MOV    SI,CUR_OFFSET          ;Retrieve starting offset.
  1161.                MOV    DI,2*160+2             ;Point to row two of screen.
  1162.                MOV    BH,21                  ;21 lines to write.
  1163. NEXT_WRITE:    MOV    CX,40                  ;40 characters per line.
  1164. NEXT_CHAR:     LODSB                         ;Get a byte.
  1165.                MOV    BL,AL                  ;Save it in BL.
  1166.                CALL   WRITE_SCREEN           ;Write them.
  1167.                LOOP   NEXT_CHAR
  1168.                ADD    DI,80                  ;Bump pointer to next line.
  1169.                DEC    BH                     ;Do all 21 lines.
  1170.                JNZ    NEXT_WRITE
  1171.                RET
  1172.  
  1173. ;------------------------------------------------------------;
  1174. ; This subroutine displays the directory by writing directly ;
  1175. ; to the screen buffer. To avoid screen noise (snow) on the  ;
  1176. ; color card, the horizontal retrace has to be monitored.    ;
  1177. ;------------------------------------------------------------;
  1178.  
  1179. WRITE_SCREEN:  MOV    DX,STATUS_REG          ;Retrieve status register.
  1180.                MOV    AX,VIDEO_SEG           ;Point to screen segment.
  1181.                MOV    ES,AX
  1182.  
  1183. HORZ_RET:      IN     AL,DX                  ;Get status.
  1184.                TEST   AL,1                   ;Is it low?
  1185.                JNZ    HORZ_RET               ;If not, wait until it is.
  1186.                CLI                           ;No more interrupts.
  1187.  
  1188. WAIT:          IN     AL,DX                  ;Get status.
  1189.                TEST   AL,1                   ;Is it high?
  1190.                JZ     WAIT                   ;If no, wait until it is.
  1191.                MOV    AL,BL                  ;Retrieve character; now it's OK
  1192.                STOSB                         ; to write to screen buffer.
  1193.                STI                           ;Interrupts back on.
  1194.                INC    DI                     ;Bump pointer past attribute.
  1195.                PUSH   CS
  1196.                POP    ES
  1197.                RET                           ;Return
  1198.  
  1199. ;-----------------------------------------------------------------------;
  1200. ; These two subroutines clear either the messages or the entire screen. ;
  1201. ;-----------------------------------------------------------------------;
  1202.  
  1203. CLEAR_MSG:     MOV    CX,162BH               ;Row 22; column 43.
  1204.                MOV    DX,174FH               ;Row 23; column 79.
  1205.                JMP    SHORT CLEAR_WINDOW
  1206.  
  1207. CLS:           XOR    CX,CX
  1208.                MOV    DX,184FH               ;Entire screen.
  1209.  
  1210. CLEAR_WINDOW:  PUSH   BP
  1211.                PUSH   BX
  1212.                MOV    BH,NORMAL              ;Clear with original attribute.
  1213.                MOV    AX,600H
  1214.                INT    10H
  1215.                POP    BX
  1216.                POP    BP
  1217.                RET
  1218.  
  1219. ;-----------------------------------------;
  1220. ; These subroutines display the messages. ;
  1221. ;-----------------------------------------;
  1222.  
  1223. DISPLAY_TEXT:  CALL   SET_CURSOR             ;Move cursor.
  1224. GET_TEXT:      LODSB
  1225.                CMP    AL,0                   ;Zero marks end of string.
  1226.                JZ     END_TEXT
  1227.                CALL   WRITE_TEXT
  1228.                JMP    SHORT GET_TEXT
  1229. END_TEXT:      RET
  1230.  
  1231. WRITE_TEXT:    PUSH   SI                     ;BIOS does not save SI.
  1232.                MOV    AH,0EH                 ;Write teletype.
  1233.                INT    10H
  1234.                POP    SI
  1235.                RET
  1236.  
  1237. ;---------------------------------------------------------;
  1238. ; These four subroutines move the cursor, get the current ;
  1239. ; directory, beep the speaker or get a keystroke.         ;
  1240. ;---------------------------------------------------------;
  1241.  
  1242. SET_CURSOR:    PUSH   SI
  1243.                XOR    BH,BH                  ;Page zero.
  1244.                MOV    AH,2                   ;Set cursor.
  1245.                INT    10H
  1246.                POP    SI
  1247.                RET
  1248.  
  1249. GET_DIR:       MOV    BYTE PTR [SI],'\'      ;DOS doesn't preface directory
  1250.                INC    SI                     ; with slash so we must.
  1251.                XOR    DL,DL
  1252.                MOV    AH,47H                 ;Retrieve default directory.
  1253.                INT    21H
  1254.                RET
  1255.  
  1256. BEEP:          MOV    DL,7                   ;Beep via DOS.
  1257.                MOV    AH,2
  1258.                INT    21H
  1259.                RET
  1260.  
  1261. READ_KEY:      MOV    AH,0                   ;Retrieve keystroke via BIOS.
  1262.                INT    16H
  1263.                RET
  1264.  
  1265. ;-----------------------------------------------;
  1266. ; These subroutines turn the cursor off and on. ;
  1267. ;-----------------------------------------------;
  1268.  
  1269. CURSOR_OFF:    MOV    CX,2000H
  1270.                JMP    SHORT SET_TYPE
  1271.  
  1272. CURSOR_ON:     MOV    CX,CURSOR_TYPE
  1273.  
  1274. SET_TYPE:      MOV    AH,1
  1275.                INT    10H
  1276.                RET
  1277.  
  1278. ;--------------------------------------------------;
  1279. ; This long subroutine stores the filename in DIR  ;
  1280. ; format. That is, filename, bytes, date and time. ;
  1281. ;--------------------------------------------------;
  1282.  
  1283. BUFFER_NAME:   MOV    SI,158                 ;Point to filename.
  1284.                MOV    CX,12                  ;Store 12 bytes of filename.
  1285. NEXT_STORE:    LODSB                         ;Get a byte.
  1286.                CMP    AL,0                   ;End of filename?
  1287.                JZ     END_STORE              ;If yes, finish with blanks.
  1288.                CMP    AL,'.'                 ;Is it the period?
  1289.                JNZ    STORE_BYTE             ;If no, store.
  1290.                SUB    CX,3                   ;Else store 3 spaces.
  1291.                MOV    AL,32
  1292.                REP    STOSB
  1293.                ADD    CX,3
  1294.                JMP    SHORT NEXT_STORE       ;Get next byte.
  1295.  
  1296. STORE_BYTE:    STOSB                         ;Store byte.
  1297.                LOOP   NEXT_STORE             ;Get next byte.
  1298. END_STORE:     MOV    AL,32                  ;Pad balance with spaces.
  1299.                REP    STOSB
  1300.  
  1301. FILE_SIZE:     PUSH   DI                     ;Save pointer.
  1302.                ADD    DI,8                   ;Move to end of bytes field.
  1303.                MOV    DX,DS:[154]            ;Retrieve high and low words
  1304.                MOV    AX,DS:[156]            ; of bytes.
  1305.                MOV    BX,10                  ;Convert to decimal; divide by 10.
  1306.                STD                           ;Reverse direction.
  1307.  
  1308. NEXT_SIZE:     MOV    CX,DX                  ;Low word in CX.
  1309.                XOR    DX,DX                  ;Zero in high half.
  1310.                DIV    BX                     ;Convert to decimal.
  1311.                XCHG   AX,CX                  ;Retrieve low word.
  1312.                DIV    BX
  1313.                XCHG   AX,DX                  ;Retrieve remainder.
  1314.                ADD    AL,'0'                 ;Convert to ASCII.
  1315.                STOSB                         ;Store it.
  1316.                MOV    AX,CX                  ;Are we done?
  1317.                OR     CX,DX
  1318.                JNZ    NEXT_SIZE              ;If no, divide again.
  1319.  
  1320.                CLD                           ;Back to forward direction.
  1321.                POP    DI                     ;Retrieve pointer.
  1322.                ADD    DI,11                  ;Move to date field.
  1323. DATE:          MOV    DX,DS:[152]            ;Retrieve date.
  1324.                MOV    AX,DX
  1325.                MOV    CL,5                   ;Shift to lowest bits.
  1326.                ROR    AX,CL
  1327.                AND    AX,0FH                 ;Mask off all but month.
  1328.                MOV    CL,0FFH                ;Flag as no leading zeros.
  1329.                MOV    CH,'-'                 ;Delimiting character.
  1330.                CALL   STORE_WORD             ;Store it.
  1331.  
  1332.                MOV    AX,DX                  ;Retrieve date.
  1333.                AND    AX,1FH                 ;Mask off all but day.
  1334.                MOV    CL,0                   ;Flag include leading zeros.
  1335.                MOV    CH,'-'
  1336.                CALL   STORE_WORD             ;Store it.
  1337.  
  1338.                MOV    AX,DX                  ;Retrieve date for last time.
  1339.                MOV    CL,9
  1340.                ROR    AX,CL
  1341.                AND    AX,7FH                 ;Mask off all but year.
  1342.                ADD    AX,80                  ;Adjust to ASCII.
  1343.                CMP    AX,100                 ;Past year 2000?
  1344.                JB     DISPLAY_DATE           ;If no, display. Else, adjust for
  1345.                SUB    AX,100                 ; next century. (Planning ahead!)
  1346. DISPLAY_DATE:  MOV    CL,0                   ;Display leading zeros.
  1347.                MOV    CH,32
  1348.                CALL   STORE_WORD             ;Store it.
  1349.  
  1350. TIME:          INC    DI                     ;Move to time field.
  1351.                MOV    DX,DS:[150]            ;Retrieve time.
  1352.                MOV    AX,DX
  1353.                MOV    CL,11                  ;Shift to hours bits.
  1354.                ROR    AX,CL
  1355.                AND    AX,1FH                 ;Mask off all but hours.
  1356.                PUSH   AX
  1357.                CMP    AX,12                  ;Past noon?
  1358.                JBE    MERIDIAN
  1359.                SUB    AX,12                  ;If yes, adjust.
  1360. MERIDIAN:      CMP    AX,0                   ;Midnight?
  1361.                JNZ    NOT_MIDNIGHT
  1362.                MOV    AX,12                  ;If yes, adjust.
  1363. NOT_MIDNIGHT:  MOV    CL,0FFH                ;Suppress leading zeros.
  1364.                MOV    CH,':'
  1365.                CALL   STORE_WORD             ;Store it.
  1366.  
  1367.                MOV    AX,DX                  ;Retrieve time.
  1368.                MOV    CL,5                   ;Shift to minutes bits.
  1369.                ROR    AX,CL
  1370.                AND    AX,3FH                 ;Mask off all but minutes.
  1371.                MOV    CL,0
  1372.                POP    DX                     ;Retrieve hours.
  1373.                MOV    CH,'p'                 ;Assume PM.
  1374.                CMP    DX,12                  ;Is it PM?
  1375.                JAE    PM
  1376.                MOV    CH,'a'                 ;If no, AM.
  1377.  
  1378. PM:            CALL   STORE_WORD             ;Store it.
  1379.                MOV    AL,'H'
  1380.                TEST   BYTE PTR DS:[149],6    ;Is it a hidden or system file?
  1381.                JZ     NOT_HIDDEN
  1382.                STOSB                         ;If yes, tack on an "H".
  1383.                RET
  1384. NOT_HIDDEN:    INC    DI
  1385.                RET
  1386.  
  1387. ;-------------------------------;
  1388.  
  1389. STORE_WORD:    DIV    BL                     ;Divide by ten.
  1390.                ADD    AX,'00'                ;Convert to ASCII.
  1391.                CMP    CL,0                   ;Are we to display leading zero?
  1392.                JZ     STORE_IT               ;If yes, store as is.
  1393.                CMP    AL,'0'                 ;Is it a leading zero?
  1394.                JNZ    STORE_IT               ;If no, store it.
  1395.                MOV    AL,32                  ;Else, store a space.
  1396. STORE_IT:      STOSW
  1397.                MOV    AL,CH                  ;Store delimiter character also.
  1398.                STOSB
  1399.                RET
  1400.  
  1401. ;-------------------------------------------------;
  1402. ; Approximate 700 filename buffer at end of code. ;
  1403. ;-------------------------------------------------;
  1404.  
  1405. CURRENT_DIR    DB     0
  1406. PURGE_DIR      EQU    CURRENT_DIR+68
  1407. FILE_NAME      EQU    PURGE_DIR+66
  1408. BUFFER         EQU    FILE_NAME+13
  1409.  
  1410. CODE ENDS
  1411. END  START
  1412.